home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / games_d / gnuchess.zip / GNUAN.C < prev    next >
Text File  |  1990-12-21  |  22KB  |  832 lines

  1. /*
  2.   gnuan.c - Analysis interface for gnuchess.
  3.  
  4.   Revision: 1990-04-18
  5.  
  6.   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  7.   Copyright (c) 1988, 1989, 1990  John Stanback
  8.  
  9.   This file is part of CHESS.
  10.  
  11.   CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  12.   WARRANTY.  No author or distributor accepts responsibility to anyone for
  13.   the consequences of using it or for whether it serves any particular
  14.   purpose or works at all, unless he says so in writing.  Refer to the CHESS
  15.   General Public License for full details.
  16.  
  17.   Everyone is granted permission to copy, modify and redistribute CHESS, but
  18.   only under the conditions described in the CHESS General Public License.
  19.   A copy of this license is supposed to have been given to you along with
  20.   CHESS so you can know your rights and responsibilities.  It should be in a
  21.   file named COPYING.  Among other things, the copyright notice and this
  22.   notice must be preserved on all copies.
  23. */
  24.  
  25. /*
  26.   This is a front end for a chess analysis program.  It takes a file of moves
  27.   in algebraic notation and creates a file containing each move that was
  28.   made, the move it would have made, the score it would give itself after
  29.   making the move it recommended, and the depth it searched for the move.
  30.  
  31.   This is a modification of nondsp.c.  I have cut out code that was not needed
  32.   for this application such as the help and edit functions.  Most of the
  33.   modifications were done in InputCommand.
  34. */
  35.  
  36. /*
  37.   This file will generate two different analysis programs.  One is meant to
  38.   be run as a background process inwhich the in and out files are predefined.
  39.   The other is meant to be run in the foreground where it will prompt you for
  40.   the name of the file with the game in it, the maximum depth the search should
  41.   be conducted to and the time limit per move.  It would be nice to be able to
  42.   give these parameters on the command line, but that would mean changing main
  43.   which is in the gnuchess.c file.
  44.  
  45.   For each move it will analyse the move until either it has run out of time
  46.   or it has reached the maximum depth.
  47.  
  48.   To build the version for background processing define BACKGROUND_ANALYSIS
  49.   either at the top of this file, or in compilation.  The files and depth
  50.   used are defined below.  They are MAX_DEPTH, MAX_TIME, OUT_FILE, IN_FILE
  51.   and PROG_FILE.  The PROG_FILE is a file that will be updated as each move is
  52.   analysed so you can check its progress.  This is only updated when running
  53.   the BACKGROUND_ANALYSIS version.  In the version where the filename and
  54.   depth are entered at runtime, the output goes to stdout.
  55. */
  56.  
  57. /* #define BACKGROUND_ANALYSIS 1 */
  58.  
  59. #define MAX_DEPTH  15
  60. #define MAX_TIME   20
  61. #define OUT_FILE   "/pad/gnuan.out"
  62. #define IN_FILE    "/pad/gnuan.in"
  63. #define PROG_FILE  "/pad/gnuan.prog"
  64.  
  65.  
  66. #include <ctype.h>
  67. #include <signal.h>
  68. #ifdef MSDOS
  69. #include <dos.h>
  70. #include <conio.h>
  71. #include <stdlib.h>
  72. #include <string.h>
  73. #include <time.h>
  74. #else
  75. #include <sys/param.h>
  76. #include <sys/types.h>
  77. #include <sys/file.h>
  78. #include <sys/ioctl.h>
  79. void TerminateSearch (int), Die (int);
  80. #endif /* MSDOS */
  81.  
  82. #include "gnuchess.h"
  83.  
  84. #define pxx " PNBRQK"
  85. #define qxx " pnbrqk"
  86. #define rxx "12345678"
  87. #define cxx "abcdefgh"
  88. #define printz printf
  89. #define scanz scanf
  90.  
  91. static char mvstr[4][6];
  92. static char* ColorStr[2] = {"White", "Black"};
  93. static long evrate;
  94. static int mycnt1, mycnt2;
  95. static int ahead;
  96.  
  97. static FILE *fpin;
  98. static FILE *fpout;
  99.  
  100. #ifdef BACKGROUND_ANALYSIS
  101. static FILE *fpprog;
  102. #endif
  103.  
  104. static char white_actual_move[20];
  105. static char black_actual_move[20];
  106. static char white_suggest_move[20];
  107. static char black_suggest_move[20];
  108. static int  white_score;
  109. static int  black_score;
  110. static int  white_moving;
  111. static int  current_depth;
  112. static int  current_score;
  113. static int  enable_update_display = 0;
  114.  
  115.  
  116. void
  117. Initialize (void)
  118. {
  119.   mycnt1 = mycnt2 = 0;
  120. }
  121.  
  122. void
  123. ExitChess (void)
  124. {
  125.   ListGame ();
  126.   exit (0);
  127. }
  128.  
  129. #ifndef MSDOS                           /* never called!!! */
  130. void
  131. Die (int sig)
  132. {
  133.     ExitChess ();
  134. }
  135. #endif /* MSDOS */
  136.  
  137. void
  138. TerminateSearch (int sig)
  139. {
  140. #ifdef MSDOS
  141.   sig++;                                /* shut up the compiler */
  142. #endif /* MSDOS */
  143.   flag.timeout   = true;
  144.   flag.bothsides = false;
  145. }
  146.  
  147. void
  148. algbr (short int f, short int t, short int flag)
  149.  
  150. /*
  151.    Generate move strings in different formats.
  152. */
  153.  
  154. {
  155.   int m3p;
  156.  
  157.   if (f != t)
  158.     {
  159.       /* algebraic notation */
  160.       mvstr[0][0] = cxx[column (f)];
  161.       mvstr[0][1] = rxx[row (f)];
  162.       mvstr[0][2] = cxx[column (t)];
  163.       mvstr[0][3] = rxx[row (t)];
  164.       mvstr[0][4] = mvstr[3][0] = '\0';
  165.       if ((mvstr[1][0] = pxx[board[f]]) == 'P')
  166.         {
  167.           if (mvstr[0][0] == mvstr[0][2])       /* pawn did not eat */
  168.             {
  169.               mvstr[2][0] = mvstr[1][0] = mvstr[0][2];  /* to column */
  170.               mvstr[2][1] = mvstr[1][1] = mvstr[0][3];  /* to row */
  171.               m3p = 2;
  172.             }
  173.           else
  174.             /* pawn ate */
  175.             {
  176.               mvstr[2][0] = mvstr[1][0] = mvstr[0][0];  /* from column */
  177.               mvstr[2][1] = mvstr[1][1] = mvstr[0][2];  /* to column */
  178.               mvstr[2][2] = mvstr[0][3];
  179.               m3p = 3;          /* to row */
  180.             }
  181.           mvstr[2][m3p] = mvstr[1][2] = '\0';
  182.           if (flag & promote)
  183.             {
  184.               mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = qxx[flag & pmask];
  185.               mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[0][5] = '\0';
  186.             }
  187.         }
  188.       else
  189.         /* not a pawn */
  190.         {
  191.           mvstr[2][0] = mvstr[1][0];
  192.           mvstr[2][1] = mvstr[0][1];
  193.           mvstr[2][2] = mvstr[1][1] = mvstr[0][2];      /* to column */
  194.           mvstr[2][3] = mvstr[1][2] = mvstr[0][3];      /* to row */
  195.           mvstr[2][4] = mvstr[1][3] = '\0';
  196.           strcpy (mvstr[3], mvstr[2]);
  197.           mvstr[3][1] = mvstr[0][0];
  198.           if (flag & cstlmask)
  199.             {
  200.               if (t > f)
  201.                 {
  202.                   strcpy (mvstr[1], "o-o");
  203.                   strcpy (mvstr[2], "O-O");
  204.                 }
  205.               else
  206.                 {
  207.                   strcpy (mvstr[1], "o-o-o");
  208.                   strcpy (mvstr[2], "O-O-O");
  209.                 }
  210.             }
  211.         }
  212.     }
  213.   else
  214.     mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
  215. }
  216.  
  217.  
  218. int
  219. VerifyMove (char *s, short int iop, unsigned short int *mv)
  220.  
  221. /*
  222.    Compare the string 's' to the list of legal moves available for the
  223.    opponent. If a match is found, make the move on the board.
  224. */
  225.  
  226. {
  227.   static short pnt, tempb, tempc, tempsf, tempst, cnt;
  228.   static struct leaf xnode;
  229.   struct leaf *node;
  230.  
  231.   *mv = 0;
  232.   if (iop == 2)
  233.     {
  234.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  235.       return (false);
  236.     }
  237.   cnt = 0;
  238.   MoveList (opponent, 2);
  239.   pnt = TrPnt[2];
  240.   while (pnt < TrPnt[3])
  241.     {
  242.       node = &Tree[pnt++];
  243.       algbr (node->f, node->t, (short) node->flags);
  244.       if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 ||
  245.           strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0)
  246.         {
  247.           cnt++;
  248.           xnode = *node;
  249.         }
  250.     }
  251.   if (cnt == 1)
  252.     {
  253.       MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  254.       if (SqAtakd (PieceList[opponent][0], computer))
  255.         {
  256.           UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  257.           printz ("Illegal move\n");
  258.           return (false);
  259.         }
  260.       else
  261.         {
  262.           if (iop == 1)
  263.             return (true);
  264. /*        UpdateDisplay (xnode.f, xnode.t, 0, (short) xnode.flags); */
  265.           if ((board[xnode.t] == pawn)
  266.               || (xnode.flags & capture)
  267.               || (xnode.flags & cstlmask))
  268.             {
  269.               Game50 = GameCnt;
  270.               ZeroRPT ();
  271.             }
  272.           GameList[GameCnt].depth = GameList[GameCnt].score = 0;
  273.           GameList[GameCnt].nodes = 0;
  274.           ElapsedTime (1);
  275.           GameList[GameCnt].time = (short) et;
  276.           TimeControl.clock[opponent] -= et;
  277.           --TimeControl.moves[opponent];
  278.           *mv = (xnode.f << 8) | xnode.t;
  279.           algbr (xnode.f, xnode.t, false);
  280.           return (true);
  281.         }
  282.     }
  283. #ifdef CHESSTOOL
  284.   printz ("Illegal move\n");
  285. #else
  286.   if (cnt > 1)
  287.     ShowMessage ("Ambiguous Move!");
  288. #endif
  289.   return (false);
  290. }
  291.  
  292. void
  293. help (void)
  294. {
  295. }
  296.  
  297. void
  298. EditBoard (void)
  299. /*
  300.    Set up a board position. Pieces are entered by typing the piece followed
  301.    by the location. For example, Nf3 will place a knight on square f3.
  302. */
  303.  
  304. {
  305. }
  306.  
  307. void
  308. SetupBoard (void)
  309.  
  310. /*
  311.    Compatibility with Unix chess and the nchesstool.
  312.    Set up a board position. Eight lines of eight characters are used
  313.    to setup the board. a8-h8 is the first line.
  314.    Black pieces are  represented  by  uppercase characters.
  315. */
  316.  
  317. {
  318. }
  319.  
  320. void
  321. ShowDepth (char ch)
  322. {
  323. #ifdef MSDOS
  324.   ch++;                                 /* shut up the compiler */
  325. #endif /* MSDOS */
  326. }
  327.  
  328. void
  329. ShowResults (short int score, unsigned short int *bstline, char ch)
  330. {
  331.     current_score = score;
  332.     current_depth = Sdepth;
  333. }
  334.  
  335. void
  336. SearchStartStuff (short int side)
  337. {
  338.   signal (SIGINT, TerminateSearch);
  339. #ifndef MSDOS
  340.   signal (SIGQUIT, TerminateSearch);
  341. #endif /* MSDOS */
  342.   if (flag.post)
  343.     {
  344.       fprintf (stderr, "\nMove# %d    Target= %ld    Clock: %ld\n",
  345.                TCmoves - TimeControl.moves[side] + 1,
  346.                ResponseTime, TimeControl.clock[side]);
  347.     }
  348. }
  349.  
  350. void
  351. OutputMove (void)
  352. {
  353.     if(white_moving) {
  354.         strcpy(white_suggest_move, mvstr[0]);
  355.         white_score = current_score;
  356.     } else {
  357.         strcpy(black_suggest_move, mvstr[0]);
  358.         black_score = current_score;
  359.     }
  360. }
  361.  
  362. void
  363. ElapsedTime (short int iop)
  364. /*
  365.    Determine the time that has passed since the search was started. If the
  366.    elapsed time exceeds the target (ResponseTime+ExtraTime) then set timeout
  367.    to true which will terminate the search.
  368. */
  369. {
  370.   if (ahead)
  371.     {
  372. #ifndef MSDOS
  373.       long nchar;
  374.       ioctl(0, FIONREAD, &nchar);
  375.       if (nchar)
  376. #else
  377.       if (kbhit())
  378. #endif /* MSDOS */
  379.         {
  380.           flag.timeout = true;
  381.           flag.bothsides = false;
  382.         }
  383.     }
  384.   et = time ((long *) 0) - time0;
  385.   if (et < 0)
  386.     et = 0;
  387.   ETnodes += 50;
  388.   if (et > et0 || iop == 1)
  389.     {
  390.       if (et > ResponseTime + ExtraTime && Sdepth > 1)
  391.         flag.timeout = true;
  392.       et0 = et;
  393.       if (iop == 1)
  394.         {
  395.           time0 = time ((long *) 0);
  396.           et0 = 0;
  397.         }
  398.       if (et > 0)
  399.         /* evrate used to be Nodes / cputime I dont` know why */
  400.         evrate = NodeCnt / (et + ft);
  401.       else
  402.         evrate = 0;
  403.       ETnodes = NodeCnt + 50;
  404.     }
  405. }
  406.  
  407. void
  408. SetTimeControl (void)
  409. {
  410.   if (TCflag)
  411.     {
  412.       TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
  413.       TimeControl.clock[white] = TimeControl.clock[black] = 60L * TCminutes;
  414.     }
  415.   else
  416.     {
  417.       TimeControl.moves[white] = TimeControl.moves[black] = 0;
  418.       TimeControl.clock[white] = TimeControl.clock[black] = 0;
  419.       Level = 60L * TCminutes;
  420.     }
  421.   et = 0;
  422.   ElapsedTime (1);
  423. }
  424.  
  425. void
  426. ClrScreen (void)
  427. {
  428. #ifndef CHESSTOOL
  429.   printz ("\n");
  430. #endif
  431. }
  432.  
  433. void
  434. UpdateDisplay (short int f, short int t, short int redraw, short int isspec)
  435. {
  436. #ifndef CHESSTOOL
  437.   short r, c, l;
  438.   if(!enable_update_display) return;
  439.   if (redraw)
  440.     {
  441.       fprintf(fpout, "\n");
  442.       for (r = 7; r >= 0; r--)
  443.         {
  444.           for (c = 0; c <= 7; c++)
  445.             {
  446.               if (flag.reverse)
  447.                 l = locn (7 - r, 7 - c);
  448.               else
  449.                 l = locn (r, c);
  450.               if (color[l] == neutral)
  451.                 fprintf (fpout, " -");
  452.               else if (color[l] == white)
  453.                 fprintf (fpout, " %c", qxx[board[l]]);
  454.               else
  455.                 fprintf (fpout, " %c", pxx[board[l]]);
  456.             }
  457.           fprintf(fpout, "\n");
  458.         }
  459.       fprintf(fpout, "\n");
  460.     }
  461. #endif /* CHESSTOOL */
  462. #ifdef MSDOS
  463.   f++; t++; isspec++;                   /* shut up the compiler */
  464. #endif /* MSDOS */
  465. }
  466.  
  467. void
  468. GetGame (void)
  469. {
  470. }
  471.  
  472. void
  473. SaveGame (void)
  474. {
  475. }
  476.  
  477. void
  478. ListGame (void)
  479. {
  480. }
  481.  
  482. void
  483. Undo (void)
  484. /*
  485.    Undo the most recent half-move.
  486. */
  487.  
  488. {
  489.   short f, t;
  490.   f = GameList[GameCnt].gmove >> 8;
  491.   t = GameList[GameCnt].gmove & 0xFF;
  492.   if (board[t] == king && distance (t, f) > 1)
  493.     (void) castle (GameList[GameCnt].color, f, t, 2);
  494.   else
  495.     {
  496.       /* Check for promotion: */
  497.       if ((row (f) == 6 && row (t) == 7) || (row (f) == 1 && row (t) == 0))
  498.         {
  499.           int g, from = f, c= color[t];
  500.           for (g = GameCnt - 1; g >= 0; g--)
  501.             if (GameList[g].gmove & 0xFF == from)
  502.               from = GameList[g].gmove >> 8;
  503.           if ((row(from) == 1 && row(f) == 6)
  504.              || (row(from) == 6 && row(f) == 1))
  505.             board[t] = pawn;
  506.         }
  507.  
  508.       board[f] = board[t];
  509.       color[f] = color[t];
  510.       board[t] = GameList[GameCnt].piece;
  511.       color[t] = GameList[GameCnt].color;
  512.       if (color[t] != neutral)
  513.       Mvboard[t]--;
  514.       Mvboard[f]--;
  515.     }
  516.   if (TCflag)
  517.     ++TimeControl.moves[color[f]];
  518.   GameCnt--;
  519.   computer = otherside[computer];
  520.   opponent = otherside[opponent];
  521.   flag.mate = false;
  522.   Sdepth = 0;
  523. /*  UpdateDisplay (0, 0, 1, 0); */
  524.   InitializeStats ();
  525. }
  526.  
  527. void
  528. ShowMessage (char *s)
  529. {
  530.   fprintf (stderr, "%s\n", s);
  531. }
  532.  
  533. void
  534. ShowSidetomove (void)
  535. {
  536. }
  537.  
  538. void
  539. PromptForMove (void)
  540. {
  541. #ifndef CHESSTOOL
  542.   printz ("\nYour move is? ");
  543. #endif /* CHESSTOOL */
  544. }
  545.  
  546.  
  547. void
  548. ShowCurrentMove (short int pnt, short int f, short int t)
  549. {
  550. #ifdef MSDOS
  551.   f++; t++; pnt++;                      /* shut up the compiler */
  552. #endif /* MSDOS */
  553. }
  554.  
  555. void
  556. ChangeAlphaWindow (void)
  557. {
  558.   printz ("window: ");
  559.   scanz ("%hd", &Awindow);
  560. }
  561.  
  562. void
  563. ChangeBetaWindow (void)
  564. {
  565.   printz ("window: ");
  566.   scanz ("%hd", &Bwindow);
  567. }
  568.  
  569. void
  570. GiveHint (void)
  571. {
  572.   algbr ((short) (hint >> 8), (short) (hint & 0xFF), false);
  573.   fprintf (stderr, "Hint: %s\n", mvstr[0]);
  574. }
  575.  
  576. void
  577. SelectLevel (void)
  578. {
  579. }
  580.  
  581. void
  582. ChangeSearchDepth (void)
  583. {
  584.   printz ("depth= ");
  585.   scanz ("%hd", &MaxSearchDepth);
  586. }
  587.  
  588. void
  589. SetContempt (void)
  590. {
  591.   printz ("contempt= ");
  592.   scanz ("%hd", &contempt);
  593. }
  594.  
  595. void
  596. ChangeXwindow (void)
  597. {
  598.   printz ("xwndw= ");
  599.   scanz ("%hd", &xwndw);
  600. }
  601.  
  602. void
  603. TestSpeed(void (*f) (short int side, short int ply))
  604. {
  605.   short i;
  606.   long cnt, rate, t1, t2;
  607.  
  608.   t1 = time (0);
  609.   for (i = 0; i < 10000; i++)
  610.     {
  611.       f (opponent, 2);
  612.     }
  613.   t2 = time (0);
  614.   cnt = 10000L * (TrPnt[3] - TrPnt[2]);
  615.   rate = cnt / (t2 - t1);
  616.   printz ("Nodes= %ld Nodes/sec= %ld\n", cnt, rate);
  617. }
  618.  
  619.  
  620. int GetNextMove(char *buffer)
  621.     {
  622.         char current;
  623.  
  624.         while((current = fgetc(fpin)) == ' ' || current == '\n') ;
  625.         if(current == EOF) return(0);
  626.         while(current != ' ' && current != '\n' && current != EOF) {
  627.             if(!(current == '-' || current == 'x' || current == 'X')) {
  628.                 *buffer++ = current;
  629.             }
  630.             current = fgetc(fpin);
  631.         }
  632.         *buffer = '\0';
  633.         return(1);
  634.     }
  635.  
  636. void InputCommand(void)
  637. /*
  638.     Open the file of moves to analyse.  Go through the file move by move
  639.     and do the following for each move.  See what gnuchess would have done
  640.     in that position.  Record the move it would have made along with the
  641.     score it would have given and the search depth.  Take back its move.
  642.     Force the move that was actually made.  Keep track of statistics such
  643.     as how many moves agreed.
  644. */
  645.  
  646. {
  647.     int i;
  648.     short ok,tmp;
  649.     int search_depth, max_minutes;
  650.     long cnt,rate,t1,t2;
  651.     unsigned short mv;
  652.     char s[80];
  653.     char infilename[255];
  654.     char outfilename[255];
  655.     char progfilename[255];
  656.     int move_number = 1;
  657.     long start_time, end_time, elapsed_time;
  658.     int total_black_moves, total_white_moves;
  659.     int same_black_moves, same_white_moves;
  660.     float white_percent, black_percent;
  661.  
  662.     /* Initialize necessary variables. */
  663.  
  664.     flag.quit = false;
  665.     flag.beep = false;
  666.     player = opponent;
  667.     enable_update_display = 1;
  668.     ft = 0;
  669.     Book = NULL;
  670.     total_black_moves = 0;
  671.     total_white_moves = 0;
  672.     same_black_moves  = 0;
  673.     same_white_moves  = 0;
  674.  
  675. #ifdef BACKGROUND_ANALYSIS
  676.  
  677.     /* Set the in files to standard ones for analysis if background processing selected. */
  678.  
  679.     strcpy(infilename,   IN_FILE);
  680.     strcpy(outfilename,  OUT_FILE);
  681.     strcpy(progfilename, PROG_FILE);
  682.     fpout = fopen(outfilename, "w");
  683.     if(fpout == NULL) {
  684.         fprintf(fpout,"This file does not exist : %s\n", outfilename);
  685.         flag.quit = 1;
  686.         return;
  687.     }
  688.  
  689.     MaxSearchDepth = MAX_DEPTH;
  690.     TCminutes = MAX_TIME;
  691.  
  692. #else
  693.  
  694.     /* Request information on where the file is and the depth an time. */
  695.  
  696.     fpout = stderr;
  697.     fprintf(fpout, "Input the file with the algebraic moves of the game.\n");
  698.     scanf("%s", infilename);
  699.  
  700.     fprintf(fpout, "\n");
  701.     do {
  702.         fprintf(fpout, "Input the search depth you want to use.  (1 to 29)\n");
  703.         scanf("%d", &search_depth);
  704.     } while(search_depth < 1 || search_depth > 29);
  705.     MaxSearchDepth = search_depth;
  706.  
  707.     fprintf(fpout, "\n");
  708.     do {
  709.         fprintf(fpout, "Input the maximun number of minutes per move you want to use.\n");
  710.         scanf("%d", &max_minutes);
  711.     } while(max_minutes < 1);
  712.     TCminutes = max_minutes;
  713.  
  714.     fprintf(fpout, "\n\n");
  715.  
  716. #endif
  717.  
  718.     fpin  = fopen(infilename, "r");
  719.     if(fpin == NULL) {
  720.         fprintf(fpout,"This file does not exist : %s\n", infilename);
  721.         flag.quit = 1;
  722.         return;
  723.     }
  724.  
  725.     TCmoves = 1;
  726.     TCflag = (TCmoves > 1);
  727.     OperatorTime = 0;
  728.     SetTimeControl();
  729.  
  730.     fpout = stdout;
  731.  
  732.     fprintf(fpout, "           Move Actual   Suggest Score Depth     Actual   Suggest Score Depth\n");
  733.     fprintf(fpout, "           ------------------------------------------------------------------\n");
  734.  
  735. #ifdef BACKGROUND_ANALYSIS
  736.  
  737.     /* Update progress in the progress file if this is running in the background. */
  738.  
  739.     fpprog = fopen(progfilename, "w");
  740.     fprintf(fpprog, "Done with move #%d.\n", move_number-1);
  741.     fclose(fpprog);
  742.  
  743. #endif
  744.  
  745.     time(&start_time);
  746.     while(1) {
  747.         opponent = black;
  748.         computer = white;
  749.         player = computer;
  750.         white_moving = 1;
  751.         if(!GetNextMove(s)) {
  752.             flag.quit = 1;
  753.             break;
  754.         }
  755.         flag.force = 0;
  756.         SelectMove(computer,1);
  757.         Undo();
  758.         flag.force = 1;
  759.         opponent = white;
  760.         computer = black;
  761.         player = opponent;
  762.         ok = VerifyMove(s,0,&mv);
  763.         if(!ok) {
  764.             fprintf(fpout, "\nBad move.  %s  Board position is: \n",s);
  765.             UpdateDisplay(0, 0, 1, 0);
  766.             flag.quit = 1;
  767.             break;
  768.         } else {
  769.             strcpy(white_actual_move, s);
  770.             fprintf(fpout, "           %3d   %-9s%-7s%5d%5d      ",move_number, white_actual_move, white_suggest_move, white_score, current_depth);
  771.             fflush(fpout);
  772.             move_number++;
  773.             total_white_moves++;
  774.             if(!strcmp(white_actual_move, white_suggest_move)) same_white_moves++;
  775.             Sdepth = 0;
  776.             ft = 0;
  777.         }
  778.         player = computer;
  779.         white_moving = 0;
  780.         if(!GetNextMove(s)) {
  781.             flag.quit = 1;
  782.             break;
  783.         }
  784.         flag.force = 0;
  785.         SelectMove(computer,1);
  786.         Undo();
  787.         flag.force = 1;
  788.         opponent = black;
  789.         computer = white;
  790.         player = opponent;
  791.         ok = VerifyMove(s,0,&mv);
  792.         if(!ok) {
  793.             fprintf(fpout, "\nBad move.  %s  Board position is: \n",s);
  794.             UpdateDisplay(0, 0, 1, 0);
  795.             flag.quit = 1;
  796.             break;
  797.         } else {
  798.             strcpy(black_actual_move, s);
  799.             fprintf(fpout, " %-9s%-7s%5d%5d\n", black_actual_move, black_suggest_move, black_score, current_depth);
  800.             fflush(fpout);
  801.  
  802. #ifdef BACKGROUND_ANALYSIS
  803.  
  804.             /* Update progress in the progress file if this is running in the background. */
  805.  
  806.             fpprog = fopen(progfilename, "w");
  807.             fprintf(fpprog, "Done with move #%d.\n", move_number-1);
  808.             fclose(fpprog);
  809. #else
  810. /*            fprintf(stderr, "Done with move #%d.\n", move_number-1); */
  811.  
  812. #endif
  813.  
  814.             total_black_moves++;
  815.             if(!strcmp(black_actual_move, black_suggest_move)) same_black_moves++;
  816.             Sdepth = 0;
  817.             ft = 0;
  818.         }
  819.     }
  820.  
  821.     white_percent = ((float) same_white_moves) * 100 / (float) total_white_moves;
  822.     black_percent = ((float) same_black_moves) * 100 / (float) total_black_moves;
  823.     fprintf(fpout, "\n           White's percentage was %5.2f%%.     Black's percentage was %5.2f%%.\n",  white_percent, black_percent);
  824.     time(&end_time);
  825.     elapsed_time = end_time - start_time;
  826.     fprintf(fpout, "\n           Elapsed time was %d seconds.\n", elapsed_time);
  827.     fclose(fpin);
  828.     fclose(fpout);
  829.     return;
  830. }
  831.  
  832.